package com.xcity.game.achievement;

import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xcity.db.entity.Player;
import com.xcity.game.event.GameEvents;
import com.xcity.pomelo.PomeloRoute;
import com.xcity.pomelo.push.msg.AchievementFinishedPush;
import com.xcity.pomelo.push.msg.DotTipPush;
import com.xcity.pomelo.request.GetAchieveListRequest;
import com.xcity.pomelo.request.ReceiveAchievementRewardRequest;
import com.xcity.pomelo.response.AchievementListResponse;
import com.xcity.pomelo.response.AchievementRewardResponse;
import com.xcity.pomelo.response.HintResponse;

import naga.x.App;
import naga.x.event.Event;
import naga.x.event.EventListener;
import naga.x.game.template.TemplateService;
import naga.x.net.Session;
import naga.x.net.annotation.OPHandler;
import naga.x.net.impl.pomelo.annotation.PomeloOP;
import naga.x.service.Service;
import naga.x.service.ServiceException;

@OPHandler
public class AchievementService implements Service, EventListener {

	private Map<AchievementGroup, List<AchievementTemplate>> group2templates = new EnumMap<AchievementGroup, List<AchievementTemplate>>(AchievementGroup.class);
	private List<AchievementTemplate> initTemplates;
	
	protected static final Logger LOG = LoggerFactory.getLogger(AchievementService.class);
	
	@Override
	public void startup() throws ServiceException {
		List<AchievementTemplate> all = App.getApp().getServiceManager().get(TemplateService.class).getTemplatesList(AchievementTemplate.class);
		for (int i = 0, size = all.size(); i < size; i++) {
			AchievementTemplate at = all.get(i);
			List<AchievementTemplate> list = group2templates.get(at.getGroup());
			if (list == null) {
				list = new ArrayList<AchievementTemplate>();
				group2templates.put(at.getGroup(), list);
			}
			list.add(at);
		}
		getInitAchievements(); // cache first
		App.getApp().getEventManager().register(this);
	}
	
	public List<AchievementTemplate> getInitAchievements() {
		if (initTemplates != null) {
			return initTemplates;
		}
		initTemplates = new ArrayList<AchievementTemplate>(group2templates.size());
		Collection<List<AchievementTemplate>> vals = group2templates.values();
		for (List<AchievementTemplate> l : vals) {
			initTemplates.add(l.get(0));
		}
		return initTemplates;
	}
	
	public List<AchievementTemplate> getTemplatesByGroup(byte group) {
		List<AchievementTemplate> list = group2templates.get(group);
		return list;
	}
	
	public AchievementTemplate getNext(AchievementTemplate template) {
		List<AchievementTemplate> list = group2templates.get(template.getGroup());
		if (list == null) {
			return null;
		}
		for (int i = 0, size = list.size(); i < size; i++) {
			AchievementTemplate temp = list.get(i);
			if (temp.getId() == template.getId() && i + 1 < size) {
				return list.get(i + 1);
			}
		}
		return null;
	}

	@Override
	public void shutdown() throws ServiceException {
	}

	@Override
	public String getId() {
		return getClass().getName();
	}
	
	@PomeloOP(PomeloRoute.ACHIEVEMENT_LIST)
	protected void requestAchievementList(Session session, GetAchieveListRequest req) {
		Player player = session.getClient();
		session.send(new AchievementListResponse(req.getSerial(), player.getAchievements().getAchievements()));
	}
	
	@PomeloOP(PomeloRoute.RECEIVE_ACHIEVEMENT_REWARD)
	protected void requestReceiveReward(Session session, ReceiveAchievementRewardRequest req) {
		Player player = session.getClient();
		try {
			Achievement achieve = player.getAchievements().reward(AchievementGroup.of(req.getAchieveId()));
			session.send(new AchievementRewardResponse(req.getSerial(), achieve));
		} catch (AchievementException e) {
			session.send(new HintResponse(req.getSerial(), e.getMessage()));
		}
//		if (error != null) {
//			session.send(new HintResponse(req.getSerial(), error));
//			return;
//		}
	}

	@Override
	public int[] getEventTypes() {
		return new int[] {
				GameEvents.EVENT_GOLD_CHANGED,
				GameEvents.EVENT_RANKING_UPPED,
				GameEvents.EVENT_TAKE_MONEY_IN_BUILD,
//				GameEvents.EVENT_CREATE_BUILDING,
				GameEvents.EVENT_BUILDING_FINISH_V2,
//				GameEvents.EVENT_BUILDING_LEVEL_UP,
//				GameEvents.EVENT_BUILDING_LEVEL_UP_OK,
				GameEvents.EVENT_BUILDING_PART_LEVEL_UP_V2,
				GameEvents.EVENT_START_BUILDING_V2,
				GameEvents.EVENT_PLAYER_LEVEL_UP,
//				GameEvents.EVENT_SELL_BUILDING,
//				GameEvents.EVENT_SYSTEM_FINE,
				GameEvents.EVENT_USE_ITEM,
				GameEvents.EVENT_BUY_ITEM,
				GameEvents.EVENT_PLAYER_LOGIN,
				GameEvents.EVENT_ACHIEVE_FINISHED,
				GameEvents.EVENT_TAKE_MONEY_IN_FRIEND_BUILD,
				GameEvents.EVENT_ROB_BUILD_MONEY,
				GameEvents.EVENT_RECHARGE,
				GameEvents.EVENT_USE_SYSTEM,
				GameEvents.EVENT_EMPLOYEE_ADDED,
				GameEvents.EVENT_PVE_SUCCESS,
				GameEvents.EVENT_ADVENTURE_STEAL,
				GameEvents.EVENT_ADVENTURE_ATTACK,
		};
	}

	@Override
	public void handleEvent(Event event) {
		Player player = event.getParameter();
		if (event.getType() == GameEvents.EVENT_ACHIEVE_FINISHED) {
			if (!player.isOnline()) {
				return;
			}
			Achievement achieve = event.getParameter(1);
			player.send(new AchievementFinishedPush(achieve.getTemplate().getGroup()/*, achieve.getTemplate().getName()*/));
			player.send(DotTipPush.ACHIEVE_FINISHED);
//			App.getApp().getServiceManager().get(MailService.class).sendSystemMail(player.getId(),
//					MessageFormat.format(MessageConst.ACHIEVE_FINISHED_MAIL_TITLE, achieve.getTemplate().getName()),
//					MessageFormat.format(MessageConst.ACHIEVE_FINISHED_MAIL_CONTENT, achieve.getTemplate().getName()));
			return;
		}
//		if (player.getAchievements() != null) {
			player.getAchievements().handleEvent(event);
//		}
	}

}
